package com.cy.demo1.controller;

import com.cy.demo1.controller.ex.*;
import com.cy.demo1.entity.User;
import com.cy.demo1.service.IUserService;
import com.cy.demo1.service.ex.InsertException;
import com.cy.demo1.service.ex.UsernameDuplicatedException;
import com.cy.demo1.service.impl.UserServiceImpl;
import com.cy.demo1.util.JsonResult;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/*
//@Controller
@RequestMapping("/users")
@RestController //=Controller + ResponseBody
public class UserController  extends BaseController{
    @Autowired
    private IUserService userService;
    @RequestMapping("/reg")
    //@ResponseBody//表示此方法的响应结果以json格式数据进行响应给到前端
    public JsonResult<Void> reg(User user){
        //创建相应结果对象
        JsonResult<Void> result =new JsonResult<>();
        try {
            userService.reg(user);
            result.setState(200);
            result.setMessage("用户名注册成功");

        } catch (UsernameDuplicatedException e) {
            result.setState(4000);
            result.setMessage("用户名被占用");
        } catch (InsertException e) {
        result.setState(5000);
        result.setMessage("注册时产生未知的异常");
    }
        return result;
    }
}

 */
//@Controller
@RequestMapping("/users")
@RestController //=Controller + ResponseBody
public class UserController  extends BaseController{
    @Autowired
    private IUserService userService;
    @RequestMapping("/reg")
    //@ResponseBody//表示此方法的响应结果以json格式数据进行响应给到前端
    /**
     * 约定大于配置：开发理念来完成，省略掉大量配置甚至注解的编写
     * 1.接收数据方式：请求处理方法的参数列表设置为pojo类型，来接受前端的数据
     * springboot会将前端的url地址中的参数名和pojo的属性名进行比较，如梭两个名称相同，则将值注入到pojo类中的对应属性上
     */
    public JsonResult<Void> reg(User user){
        userService.reg(user);

        return new JsonResult<Void>(OK);
    }
    /**
     * 2.接收数据方式：请求处理方法的参数列表设置为非自己封装的pojo类型
     * springboot会直接将请求的参数名和方法的参数名直接进行比较，如果名称相同则自动完成值的依赖注入
     */
    @RequestMapping("/login")
    public JsonResult<User> login(String username , String password, HttpSession session){
        User data = userService.login(username, password);
        //像session对象中完成数据绑定（session全局的）
        session.setAttribute("uid",data.getUid());
        session.setAttribute("username",data.getUsername());
        //获取session中绑定的数据
        System.out.println(getUidFromSession(session));
        System.out.println(getUserNameFromSession(session));
        return  new JsonResult<User>(OK,data);
    }
    @RequestMapping("/change_password")
    public JsonResult<Void> changePassword(String oldPassword,
                                           String newPassword,
                                           HttpSession session){
        Integer uid = getUidFromSession(session);
        String username = getUserNameFromSession(session);
        userService.changePassword(uid,username,oldPassword,newPassword);
        return  new  JsonResult<>(OK);
    }
    @RequestMapping("/get_by_uid")
    public JsonResult<User> getByUid(HttpSession session){
        User data = userService.getByUid(getUidFromSession(session));
        return new JsonResult<>(OK,data);
    }
    @RequestMapping("/change_info")
    public JsonResult<Void> changeInfo(User user, HttpSession session){
        //user对象有四部分的数据：username, phone , email, gender
        //uid数据需要再次封装到user对象中
        Integer uid = getUidFromSession(session);
        String username = getUserNameFromSession(session);
        userService.changeInfo(uid,username,user);
        return new JsonResult<>(OK) ;
    }

    /**
     * MultipartFile接口是SpringMVC提供的接口，为我们包装了获取文件类型的数据（任何类型的file都可接收）
     * springboot 整合了，只需要在处理请求的方法参数列表上声明一个参数类型为MultipartFile的参数，然后
     * springboot自动传递给服务文件数据赋值给这个参数
     *
     * @RequestParam 表示请求中的参数，将请求中的参数注入到请求处理方法的某个参数上，如果他们的名称不一致
     * 则可以使用@RequestParam注解进行标记和映射
     * @param session
     * @param file
     * @return
     */
    /*设置上传文件的最大值*/
    public static final int AVATAR_MAX_SIZE = 10 * 1024 * 1024;

    /*限制上传文件的类型*/
    public static final List<String> AVATAR_TYPE = new ArrayList<>();
    static {
        AVATAR_TYPE.add("image/jpeg");//images
        AVATAR_TYPE.add("image/png");
        AVATAR_TYPE.add("image/bmp");
        AVATAR_TYPE.add("image/gif");
    }

    @RequestMapping("/change_avatar")
    public JsonResult<String> changeAvatar(HttpSession session ,
                                           @RequestParam("file") MultipartFile file ){
        //判断文件是否为空
        if (file.isEmpty()){
            throw  new FileEmptyException("文件为空");
        }
        if(file.getSize() > AVATAR_MAX_SIZE){
            throw new FileSizeException("文件超出限制");
        }
        //判断文件类型是否是我们规定的和后缀类型
        String contentType = file.getContentType();//text/html
        //结合集合包含某个元素则返回值true
        if (!AVATAR_TYPE.contains(contentType)){
            throw new FileTypeException("文件类型不支持");
        }
        //文件夹上传的文件。。。/upload/文件。png
        String parent = session.getServletContext().getRealPath("/upload");

        //File对象指向这个路径。file是否存在
        File dir = new File(parent);
        if (!dir.exists()){//检测目录是否存在
            dir.mkdirs();//创建目录
        }
        //获取到这个文件UUID工具来生成字符串作为文件名
        //例如avatar01.png
        String originalFilename = file.getOriginalFilename();
        System.out.println("OriginalFilename" + originalFilename);
        //截取文件后缀
        int index = originalFilename.lastIndexOf(".");
        String suffix= originalFilename.substring(index);
        //AHSFR-S3FHGJ-KLKUJ-QYHTR.png
        String filename = UUID.randomUUID().toString().toUpperCase() + suffix;
        File dest = new File(dir,filename);//是一个空文件
        //将参数file中的数据写入空文件中
        try {
            file.transferTo(dest);//将file文件中的数据写入到dest文件
        } catch (FileStateException e ) {
            throw new FileStateException("文件状态异常");
        }catch (IOException e) {
            throw new FileUploadIOException("文件读写异常");
        }
        Integer uid = getUidFromSession(session);
        String username = getUserNameFromSession(session);
        String avatar = "/upload/" + filename;
        userService.changeAvatar(uid,avatar,username);
        //返回用户头像的路径给前端页面作为头像展示使用
        return new JsonResult<>(OK,avatar);
    }
}